﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Water.Web.Controls.TypeConverter;
using Water.Web.Controls;
using System.Data;
using Water.Architecture2.IDAL;
using System.Collections;
using System.Globalization;
using System.Web.Caching;

namespace Water.Web.Controls
{
    [ToolboxData("<{0}:ObjectDataSource runat=server></{0}:ObjectDataSource>")]
    public class ObjectDataSource : System.Web.UI.WebControls.ObjectDataSource
    {
        private string queryControlID;
        private bool canSelect;
        private bool canInsert;
        private bool canUpdate;
        private bool canDelete;

        private string matrixColumnField;
        private string groupField;
        private string valueField;
        private SummaryType summaryType = SummaryType.Sum;
        private string matrixColumnSortExpress;

        private ObjectDataSource _matrix_column_ods = null;
        
        

        [Browsable(false)]
        public DataView MatrixColumns
        {
            get 
            {
                return GetMatrixColumnsFromCache(); 
            }
        }
        [Browsable(true), GlobalizeCategory("Matrix"), GlobalizeDescription("MatrixColumnField")]
        public string MatrixColumnField
        {
            get { return matrixColumnField; }
            set { matrixColumnField = value; }
        }
        [Browsable(true), GlobalizeCategory("Matrix"), GlobalizeDescription("GroupField")]
        public string GroupField
        {
            get {
                if (string.IsNullOrEmpty(this.groupField))
                    return this.MatrixColumnField;
                return groupField; 
            }
            set { groupField = value; }
        }
        [Browsable(true), GlobalizeCategory("Matrix"), GlobalizeDescription("ValueField")]
        public string ValueField
        {
            get { return valueField; }
            set { valueField = value; }
        }
        [Browsable(true), GlobalizeCategory("Matrix"), GlobalizeDescription("SummaryType"), DefaultValue(SummaryType.Sum)]
        public SummaryType SummaryType
        {
            get { return summaryType; }
            set { summaryType = value; }
        }
        [Browsable(true), GlobalizeCategory("Matrix"), GlobalizeDescription("MatrixColumnSortExpress")]
        public string MatrixColumnSortExpress
        {
            get { return matrixColumnSortExpress; }
            set { matrixColumnSortExpress = value; }
        }

        [Browsable(true), TypeConverter(typeof(ContainerIDConver)), Category("Behavior"), GlobalizeDescription("QueryControlID")]
        public string QueryControlID
        {
            get { return queryControlID; }
            set { queryControlID = value; }
        }
        
        [Browsable(true), Category("Behavior"), GlobalizeDescription("CanSelect")]
         public bool CanSelect
        {
            get { return canSelect; }
            set { canSelect = value; }
        }

        [Browsable(true), Category("Behavior"), GlobalizeDescription("CanInsert")]
         public bool CanInsert
         {
             get { return canInsert; }
             set { canInsert = value; }
         }

        [Browsable(true), Category("Behavior"), GlobalizeDescription("CanUpdate")]
         public bool CanUpdate
         {
             get { return canUpdate; }
             set { canUpdate = value; }
         }

        [Browsable(true), Category("Behavior"), GlobalizeDescription("CanDelete")]
         public bool CanDelete
         {
             get { return canDelete; }
             set { canDelete = value; }
         }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            if (canSelect && string.IsNullOrEmpty(this.SelectMethod))
            {
                if (string.IsNullOrEmpty(this.MatrixColumnField))
                {
                    if (EnableCaching)
                        this.SelectMethod = "FindToDataSet";
                    else
                        this.SelectMethod = "FindToDataReader";
                    this.SelectCountMethod = "GetCount";
                }
                else
                {
                    this.SelectMethod = "FindMatrixToDataReader";
                    this.SelectCountMethod = "GetMatrixCount";

                    Parameter _groupParam = new Parameter("groupField", DbType.String, this.GroupField);
                    Parameter _columnParam = new Parameter("matrixColumnField", DbType.String, this.MatrixColumnField);
                    Parameter _valueParam = new Parameter("valueField", DbType.String, this.ValueField);
                    Parameter _summaryParam = new Parameter("summaryType", DbType.Object, null);//第三个参数方法传输SummaryType类型,改为在ObjectDataSource_Selecting中处理

                    Parameter _matrixColumns = new Parameter("matrixColumns",DbType.Object,null);

                    Parameter _matrixColumnSortExpress = new Parameter("matrixColumnSortExpress", DbType.String, this.MatrixColumnSortExpress);

                    this.SelectParameters.Add(_groupParam);
                    this.SelectParameters.Add(_columnParam);
                    this.SelectParameters.Add(_valueParam);
                    this.SelectParameters.Add(_summaryParam);
                    this.SelectParameters.Add(_matrixColumns);

                    #region  matrix columns init

                    _matrix_column_ods = new ObjectDataSource();
                    _matrix_column_ods.TypeName = this.TypeName;
                    _matrix_column_ods.SelectMethod = "GetMatrixColumns";

                    _matrix_column_ods.SelectParameters.Add(_groupParam);
                    _matrix_column_ods.SelectParameters.Add(_columnParam);
                    _matrix_column_ods.SelectParameters.Add(_valueParam);
                    _matrix_column_ods.SelectParameters.Add(_summaryParam);
                    _matrix_column_ods.SelectParameters.Add(_matrixColumnSortExpress);
                    
                    if (!string.IsNullOrEmpty(this.MatrixColumnField) && null != _matrix_column_ods)
                    {
                        //_matrix_column_ods.SortParameterName = "sortExpress";
                        DataSourceView _m_dsv = _matrix_column_ods.GetView("DefaultView");
                        ((System.Web.UI.WebControls.ObjectDataSourceView)_m_dsv).Selecting += new ObjectDataSourceSelectingEventHandler(ObjectDataSource_Selecting);
                    }

                    #endregion

                }

                if (!string.IsNullOrEmpty(this.queryControlID))//exist query control
                {
                    ControlParameter _cParam = new ControlParameter("whereFields",DbType.Object, this.queryControlID, "WhereFields");
                    this.SelectParameters.Add(_cParam);
                    //matrix
                    if(!string.IsNullOrEmpty(this.MatrixColumnField)&& null!=_matrix_column_ods)
                        _matrix_column_ods.SelectParameters.Add(_cParam);
                }
                else
                {
                    Parameter _cParam = new Parameter("whereFields", DbType.Object, null);
                    this.SelectParameters.Add(_cParam);
                    //matrix
                    if (!string.IsNullOrEmpty(this.MatrixColumnField) && null != _matrix_column_ods)
                        _matrix_column_ods.SelectParameters.Add(_cParam);

                }
                if (EnablePaging)
                {
                    this.MaximumRowsParameterName = "pageSize";
                    this.StartRowIndexParameterName = "startRowIndex";
                }
                this.SortParameterName = "sortExpress";

            }
            if (canInsert)
            {
                this.InsertMethod = "Insert";
                Parameter _param=new Parameter("fields",DbType.Object);
                this.InsertParameters.Add(_param);
            }
            if (canDelete)
            {
                this.DeleteMethod = "Delete";
                Parameter _param = new Parameter("fields", DbType.Object);
                this.DeleteParameters.Add(_param);
            }
            if (canUpdate)
            {
                this.UpdateMethod = "Update";
                Parameter _whereParam = new Parameter("fields", DbType.Object);
                Parameter _updateParam = new Parameter("updateFields", DbType.Object);
                this.UpdateParameters.Add(_whereParam);
                this.UpdateParameters.Add(_updateParam);
            }
        }
       
        protected override DataSourceView GetView(string viewName)
        {
            DataSourceView _dsv = base.GetView(viewName);
            ((System.Web.UI.WebControls.ObjectDataSourceView)_dsv).Selecting += new ObjectDataSourceSelectingEventHandler(ObjectDataSource_Selecting);
            return _dsv;
        }
  
        void ObjectDataSource_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
        {
            WhereFields _wf = new WhereFields();
            object _whereFieldsKey = null;
            System.Collections.ArrayList _removekey = new System.Collections.ArrayList();
            foreach (System.Collections.DictionaryEntry entry in e.InputParameters)
            {
                string _key = entry.Key.ToString();
                //处理特殊的参数 SORTEXPRESS
                if(_key.ToUpper()=="SORTEXPRESS")
                {
                    if (string.IsNullOrEmpty(e.Arguments.SortExpression))
                        e.Arguments.SortExpression = entry.Value.ToString();
                    _removekey.Add(entry.Key);
                }

                if (_key != "whereFields" && _key != "startRowIndex" && _key != "pageSize" && _key != "sortExpress" && _key != "startRowIndex"
                    && _key != "groupField" && _key != "matrixColumnField" && _key != "valueField" && _key != "summaryType" && _key != "matrixColumns" && _key != "matrixColumnSortExpress")
                {
                    _wf.Add(entry.Key.ToString(), OperatorType.Equals, entry.Value);
                    _removekey.Add(entry.Key);
                }
                if (_key == "whereFields")
                    _whereFieldsKey = entry.Key;
            }

            foreach (object _o in _removekey)
                e.InputParameters.Remove(_o);

            if (null != _whereFieldsKey)
            {
                if (null != _wf && _wf.Count > 0)
                {
                    foreach (WhereField _whereField in _wf)
                    {
                        WhereFields _temp = (WhereFields)e.InputParameters[_whereFieldsKey];
                        if (null == _temp)
                            e.InputParameters[_whereFieldsKey] = new WhereFields();
                        ((WhereFields)e.InputParameters[_whereFieldsKey]).Add(_whereField);
                    }
                }
            }
            else if (null != _wf && _wf.Count > 0)
            {
                e.InputParameters.Add("whereFields", _wf);
            }

            // 设置summaryType值
            if (!string.IsNullOrEmpty(this.MatrixColumnField))
            {
                e.InputParameters["summaryType"] = this.SummaryType;
                if (e.InputParameters.Contains("matrixColumns"))
                    e.InputParameters["matrixColumns"] = MatrixColumns;
            }
        }

        #region create matrix column
        private void CreateMatrixColumns()
        {
            if (!string.IsNullOrEmpty(this.MatrixColumnField) && null != _matrix_column_ods)
            {
                DataSourceView _m_dsv = _matrix_column_ods.GetView("DefaultView");
                _m_dsv.Select(DataSourceSelectArguments.Empty, new DataSourceViewSelectCallback(this.OnDataSourceViewSelectCallback));
            }
        }

        private void OnDataSourceViewSelectCallback(IEnumerable data)
        {
            if (data is DataView)
            {
                SaveMatrixColumnsToCache(data as DataView);
            }
        }
        #endregion

        #region cache matrix columns help method

        private StringBuilder CreateRawCacheKey()
        {
            StringBuilder builder = new StringBuilder("u", 0x400);
            builder.Append(base.GetType().GetHashCode().ToString(CultureInfo.InvariantCulture));
            builder.Append(":");
            builder.Append(this.CacheDuration.ToString(CultureInfo.InvariantCulture));
            builder.Append(':');
            builder.Append(((int)this.CacheExpirationPolicy).ToString(CultureInfo.InvariantCulture));
            builder.Append(":");
            builder.Append(this.SqlCacheDependency);
            builder.Append(":");
            builder.Append(this.TypeName);
            builder.Append(":");
            builder.Append(this.SelectMethod);
            if (this.SelectParameters.Count > 0)
            {
                builder.Append("?");
                foreach (DictionaryEntry entry in this.SelectParameters.GetValues(this.Context, this))
                {
                    builder.Append(entry.Key.ToString());
                    if ((entry.Value != null) && (entry.Value != DBNull.Value))
                    {
                        builder.Append("=");
                        builder.Append(entry.Value.ToString());
                    }
                    else if (entry.Value == DBNull.Value)
                    {
                        builder.Append("(dbnull)");
                    }
                    else
                    {
                        builder.Append("(null)");
                    }
                    builder.Append("&");
                }
            }
            return builder;
        }

        internal string CreateMasterCacheKey()
        {
            return this.CreateRawCacheKey().ToString();
        }

        internal void SaveMatrixColumnsToCache(DataView matrixColumns)
        {
            string _key = this.CreateMasterCacheKey();
            this.Page.Cache.Add(_key,matrixColumns,null,DateTime.MaxValue,TimeSpan.FromMinutes(1),CacheItemPriority.NotRemovable,null);
        }

        private DataView GetMatrixColumnsFromCache()
        {
            DataView _matrixColumns;
            string _key = this.CreateMasterCacheKey();
            object _objMatrixColumns=this.Page.Cache.Get(_key);
            if (null == _objMatrixColumns)
            {
                CreateMatrixColumns();
                _objMatrixColumns = this.Page.Cache.Get(_key);
            }
            _matrixColumns = _objMatrixColumns as DataView;
            return _matrixColumns;
            ;
        }

        #endregion



    }
}
